package com.qf.controller;


import com.qf.captcha.CaptchaCodeManager;
import com.qf.pojo.DtsAdmin;
import com.qf.service.PermissionService;
import com.qf.service.RoleService;
import com.qf.util.*;
import com.qf.util.Base64;
import com.qf.util.UUID;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.io.ByteArrayOutputStream;
import java.util.*;

@RestController
@RequestMapping("/auth")
@CrossOrigin("*")
@Api("权限相关接口，登录，注销，验证码")
public class AuthController {
    //打印日志对象
    private static final Logger logger = LoggerFactory.getLogger(AuthController.class);

    @Autowired
    private RoleService roleService;

    @Autowired
    private ApplicationContext context;

    @Autowired
    private PermissionService permissionService;

    private HashMap<String,String> systemPermMap =null;


    @GetMapping("/captchaImage")
    @ApiOperation(value = "获取验证码图片")
    public Object findCode() throws Exception{
        //生成四位随机字符串作为验证码
        String codeStr = VerifyCodeUtils.generateVerifyCode(4);
        //生成验证码唯一标识
        String uuid = UUID.randomUUID().toString(true);
        //验证码存储到内存中
        boolean flag = CaptchaCodeManager.addToCache(uuid, codeStr, 10);

        //判断验证码能否储存成功
        if (!flag){
            logger.error("生成验证码错误：{}", AdminResponseCode.AUTH_CAPTCHA_FREQUENCY.desc());
            return AdminResponseUtil.fail(AdminResponseCode.AUTH_CAPTCHA_FREQUENCY);
        }
        //生成验证码图片
        int w= 100;
        int h=40;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        VerifyCodeUtils.outputImage(w,h,outputStream,codeStr);

        //将图片唯一id和图片内容返回
        HashMap<String, Object> data = new HashMap<>();
        data.put("img", Base64.encode(outputStream.toByteArray()));
        data.put("uuid",uuid);

        return ResponseUtil.ok(data);

    }

    @RequestMapping("/login")
    public Object login(@RequestBody String body){
        String code= JacksonUtil.parseString(body,"code");
        String username = JacksonUtil.parseString(body, "username");
        String password = JacksonUtil.parseString(body, "password");
        String uuid = JacksonUtil.parseString(body, "uuid");




        if (StringUtils.isEmpty(code)||StringUtils.isEmpty(username)||
        StringUtils.isEmpty(password)||StringUtils.isEmpty(uuid)){
            return ResponseUtil.badArgument();
        }
        String captchaCode = CaptchaCodeManager.getCachedCaptcha(uuid);
        if (captchaCode==null){
            return AdminResponseUtil.fail(AdminResponseCode.AUTH_CAPTCHA_EXPIRED);
        }
        if (!code.equalsIgnoreCase(captchaCode)){
            return AdminResponseUtil.fail(AdminResponseCode.AUTH_CAPTCHA_ERROR);
        }

        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);

        try {
            subject.login(usernamePasswordToken);
        }catch (UnknownAccountException e){
            return AdminResponseUtil.fail(AdminResponseCode.ADMIN_INVALID_ACCOUNT_OR_PASSWORD);
        }catch (AuthenticationException e){
            return AdminResponseUtil.fail(AdminResponseCode.ADMIN_INVALID_AUTH);
        }
        return ResponseUtil.ok(subject.getSession().getId());

    }
    @RequestMapping("/info")
    public Object info(){
        Subject subject = SecurityUtils.getSubject();
        DtsAdmin admin = (DtsAdmin) subject.getPrincipal();

        HashMap<String, Object> data = new HashMap<>();

        data.put("name",admin.getUsername());
        data.put("avator",admin.getAvatar());

        Integer[] roleIds = admin.getRoleIds();

        Set<String> roleSet = roleService.queryByIds(roleIds);
        data.put("roles",roleSet);
        Set<String> permSet = permissionService.queryPermissionByRoleIds(roleIds);

        data.put("perms",toAPI(permSet));
        return ResponseUtil.ok(data);

    }
    @RequestMapping("/logout")
    public Object logOut(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return ResponseUtil.ok();
    }

    private Collection<String> toAPI(Set<String> permSet){
        if (systemPermMap == null){
            systemPermMap = new HashMap<>();
            String basicPackage ="com.qf";
            List<Permission> systemPersionList = PermissionUtil.listPermission(context, basicPackage);
            for (Permission permission:systemPersionList) {
                String[] perm = permission.getRequiresPermissions().value();

                String api = permission.getApi();
                systemPermMap.put(perm[0],api);
            }
        }
        Collection<String> apis = new HashSet<>();
        for (String perm:permSet){
            String api = systemPermMap.get(perm);
            apis.add(api);

            if (perm.equals("*")){
                apis.clear();
                apis.add("*");
                return apis;
            }
        }
        return apis;
    }
}
